home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / GNU / GNUPLOTsrc.lha / term / mif.trm < prev    next >
Encoding:
Text File  |  1996-01-22  |  25.5 KB  |  867 lines

  1. /* GNUPLOT -- mif.trm */
  2. /*
  3.  * Copyright (C) 1992, 1993
  4.  *
  5.  * Permission to use, copy, and distribute this software and its
  6.  * documentation for any purpose with or without fee is hereby granted, 
  7.  * provided that the above copyright notice appear in all copies and 
  8.  * that both that copyright notice and this permission notice appear 
  9.  * in supporting documentation.
  10.  *
  11.  * Permission to modify the software is granted, but not the right to
  12.  * distribute the modified code.  Modifications are to be distributed 
  13.  * as patches to released version.
  14.  *  
  15.  * This software  is provided "as is" without express or implied warranty.
  16.  * 
  17.  * This file is included by ../term.c.
  18.  *
  19.  * This terminal driver was developed for
  20.  *      gnuplot for unix version 3.0 (patchlevel 1)
  21.  *      gnuplot for unix version 3.2 (patchlevel 2)
  22.  *
  23.  * This terminal driver supports:
  24.  *      Frame Maker MIF format version 3.00
  25.  *
  26.  * Options for this terminal driver (set terminal mif [options]):
  27.  *      colour /        Draw primitives with line types >= 0 in colour (sep. 2-7)
  28.  *      monochrome      Draw primitives in black (sep. 0)
  29.  *
  30.  *      polyline /      Draw lines as continous curves
  31.  *      vectors         Draw lines as collections of vectors
  32.  *
  33.  *      help / ?        Print short usage description on stderr
  34.  *
  35.  * Properties for this terminal driver:
  36.  *     -Gnuplot size of worksheet:              MIF_XMAX * MIF_YMAX
  37.  *     -Unit in MIF output:                     cm
  38.  *     -Plot primitives with the same pen will
  39.  *      be grouped in the same MIF group.
  40.  *     -Plot primitives with line types >= 0
  41.  *      will as default be drawn in colour.
  42.  *     -Lines are plotted as collections of
  43.  *      vectors, or as continous lines (default)
  44.  *     -Plot primitives in a plot will be in a
  45.  *      Frame in MIF. Several plot Frames will
  46.  *      be collected in one large Frame.
  47.  *     -Point size of MIF output characters:    MIF_PSIZE
  48.  *     -Used font for MIF output characters:    Times
  49.  *     -Supports vertical text
  50.  *     -points and dots as characters
  51.  *     -character formats for TextLines
  52.  *
  53.  * AUTHORS:
  54.  *      Olof Franksson, Physics IV, KTH, S-100 44 Stockholm, Sweden
  55.  * 
  56.  * NEW TERMINAL FORMAT:  David C. Schooley
  57.  
  58.  * COMMENTS:
  59.  *      Send comments and/or suggestions to olof@fysik4.kth.se
  60.  * 
  61.  * CHANGES:
  62.  *        Changed to new terminal format 9/29/95            schooley@ee.gatech.edu
  63.  *      Changed order of routine declarations.          olof@fysik4.kth.se
  64.  *      Changed mechanism for pen pattern selection.    kssingvo@immd4.informatik.uni-erlangen.de
  65.  *      Support for vertical text.                      kssingvo@immd4.informatik.uni-erlangen.de
  66.  *      Fixed plot bug for "set size XS,YS", XS/YS > 1. olof@fysik4.kth.se
  67.  *
  68.  */
  69.  
  70. #ifndef GOT_DRIVER_H
  71. #include "driver.h"
  72. #endif
  73.  
  74. #ifdef TERM_REGISTER
  75. register_term(mif)
  76. #endif
  77.  
  78.  
  79.  
  80. #ifdef TERM_PROTO
  81. TERM_PUBLIC void MIF_init __P((void));
  82. TERM_PUBLIC void MIF_graphics __P((void));
  83. TERM_PUBLIC void MIF_text __P((void));
  84. TERM_PUBLIC void MIF_linetype __P((int linetype));
  85. TERM_PUBLIC void MIF_move __P((unsigned int x, unsigned int y));
  86. TERM_PUBLIC void MIF_vector __P((unsigned int x, unsigned int y));
  87. TERM_PUBLIC void MIF_put_text __P((unsigned int x, unsigned int y, char *str));
  88. TERM_PUBLIC int MIF_text_angle __P((int ang));
  89. TERM_PUBLIC void MIF_reset __P((void));
  90. TERM_PUBLIC void MIF_options __P((void));
  91. TERM_PUBLIC int MIF_justify_text __P((enum JUSTIFY mode));
  92. TERM_PUBLIC void MIF_point __P((unsigned int x, unsigned int y, int number));
  93.  
  94. /** Coordinates **/
  95. /* The cast to float is not necessary because we are dividing by a float */
  96. /* On OSK the cast to a float is not allowed in a constant expression wich */
  97. /* is used by the declaration and initialization of mif_line */
  98. /* #define GNP_TO_MIF(P)   (((float) (P)) / 1000.0)        /* Converts gnuplot units to MIF units */
  99. #define GNP_TO_MIF(P)   ((P) / 1000.0)        /* Converts gnuplot units to MIF units */
  100. #define MIF_XMAX 15000                  /* Basic unit: 0.01 mm (15cm -> 15*10*100=15000) */
  101. #define MIF_YMAX 10000                  /* Basic unit: 0.01 mm (10cm -> 10*10*100=10000) */
  102.  
  103. #define MIF_XLAST (MIF_XMAX - 1)
  104. #define MIF_YLAST (MIF_YMAX - 1)
  105.  
  106. static int insert_mif_line __P((double fx, double fy));
  107. static int proc_group_id __P((int group_id));
  108. static void free_mif_line __P((void));
  109. static void put_mif_line __P((void));
  110. static void MIF_set_font __P((char *));
  111.  
  112. #if !defined(cfree)
  113. #define cfree free
  114. #endif
  115.  
  116.  
  117. static struct mif_line { /* Line point structure specification */
  118.     float fpos_x;           /* Line point X coordinate */
  119.     float fpos_y;           /*            Y coordinate */
  120.     struct mif_line *next;  /* Pointer to next line point */
  121.     struct mif_line *prev;  /* Pointer to previous line point */
  122. } mif_line = { /* Current position structure. Adjust for orign. Local for this file. */
  123.     GNP_TO_MIF(0),
  124.     GNP_TO_MIF(MIF_YLAST),
  125.     &mif_line,
  126.     &mif_line
  127. };
  128.  
  129. /** Characters **/
  130. #define MIF_PSIZE 9                     /* Point size of used characters */
  131.  
  132. #define MIF_VCHAR (MIF_YMAX/31)         /* Distance between rows (a guess) */
  133. #define MIF_HCHAR (MIF_XMAX/95)         /* Distance between characters (a guess) */
  134.  
  135. /** Scale marks **/
  136. #define MIF_VTIC  (MIF_YMAX/150)        /* Size of scale mark (vert) */
  137. #define MIF_HTIC  (MIF_XMAX/225)        /* Size of scale mark (hor) */
  138.  
  139. /** Drawing properties **/
  140. static char mif_justify[64];                    /* How to justify the used text */
  141. static char mif_pen[64], mif_pen_width[64], mif_separation[64];         /* How to plot */
  142.  
  143. #define MIF_TEXT_HOR  0
  144. #define MIF_TEXT_VER  1
  145. static int mif_text_ang = MIF_TEXT_HOR;         /* Rotation angle of text */
  146.  
  147. #define MIF_NPENS 16                    /* Number of MIF pen types */
  148. static int mif_pentype = 0;             /* Pen type to use. Also used to create groups for graphics */
  149. #define MIF_PEN_TO_GROUP(P)     ( 1 + (P) )     /* Map pen type to group number. Must be >= 1 */
  150.  
  151. static int mif_pattern_table[MIF_NPENS] = {     /* Table, which pattern should be used for drawing */
  152.     0,                          /* border  */
  153.     1,                          /* not used */
  154.     2, 3, 4, 8, 12, 13,         /* other lines: functions, data, ... (5 is used for grid; 6,7 is (nearly) invisible) */
  155.     5,                          /* grid */
  156.     9, 10, 11, 12, 13, 14, 15   /* not used */
  157. };
  158.  
  159. /** MIF groups administration **/
  160. #define MIF_NGROUP_ID           20
  161. static struct mif_group_id {
  162.     int group_existance;
  163. #define MIF_GROUP_EXISTS        1       /* This group id should generate a MIF group */
  164. #define MIF_GROUP_NOT_EXISTS    0       /* This group id should not generate a MIF group */
  165.  
  166.     int group_id;
  167. #define MIF_INVALID_GROUP_ID    0       /* An invalid MIF group ID */
  168.  
  169. } mif_group_id[MIF_NGROUP_ID];            /* List of used group ID:s and corresponding MIF groups existance */
  170.  
  171. /** Semaphores **/
  172. static int mif_initialized = 0;        /* != 0 when output is active */
  173. static int mif_in_frame = 0;            /* != 0 when inside a plot frame */
  174. static int mif_frameno = -1;            /* Current frame number */
  175. static int mif_colour = TRUE;           /* == TRUE when colour should be used */
  176. static int mif_polyline = TRUE;         /* == TRUE when lines are drawn as continous curves */
  177.  
  178. struct mpt {                /* point definition structure */
  179.    int chr;                /* character for point */
  180.    float x_offset, y_offset;        /* offset for vertical positioning */
  181.    char *font;                /* font */
  182. };
  183.  
  184. char zgnuplot[]  = "ZGnuplot";        /* character formats */
  185. char zgnuplotp[] = "ZGnuplotP";
  186. char zgnuplotd[] = "ZGnuplotD";
  187. char *mif_font = NULL;            /* actual character format */
  188.  
  189. struct mpt mpt[POINT_TYPES+1] = {    /* point definition data */
  190.    {'.', 0.000, 0.005, zgnuplotd,    /* dot */ },
  191.  
  192.    {'G', 0.002, 0.084, zgnuplotp,    /* diamond */}, 
  193.    {';', 0.002, 0.084, zgnuplotp,    /* plus */ },
  194.    {'n', 0.002, 0.084, zgnuplotp,    /* box */ },
  195.    {'5', 0.002, 0.084, zgnuplotp,    /* X */ },
  196.    {'s', 0.002, 0.062, zgnuplotp,    /* triangle */}, 
  197.    {'K', 0.005, 0.075, zgnuplotp,    /* star */ },
  198. };
  199.  
  200. struct mpt *mif_point = &(mpt[1]);      /* diamond is offset 0, dot is offset -1 */
  201.  
  202. #endif
  203.  
  204.  
  205.  
  206. #ifndef TERM_PROTO_ONLY
  207. #ifdef TERM_BODY
  208.  
  209.  
  210.  
  211. /** Declaration of routine/s for internal use **/
  212. static int insert_mif_line();
  213. static int proc_group_id();
  214.  
  215. /** Routine/s **/
  216.  
  217. /* Called when this terminal type is set in order to parse options */
  218. void MIF_options()
  219. {
  220.     extern char term_options[];     /* Declared in ../setshow.c */
  221.  
  222.     if (!END_OF_COMMAND) {
  223.         /* Colour options */
  224.         if (!END_OF_COMMAND && almost_equals(c_token, "m$onochrome")) {    /* Compare up to $ */
  225.             mif_colour = FALSE;
  226.             c_token++;
  227.         }
  228.         if (!END_OF_COMMAND && almost_equals(c_token, "c$olour")) {   /* Compare up to $ */
  229.             mif_colour = TRUE;
  230.             c_token++;
  231.         }
  232.  
  233.         /* Curve options */
  234.         if (!END_OF_COMMAND && almost_equals(c_token, "v$ectors")) {   /* Compare up to $ */
  235.             mif_polyline = FALSE;
  236.             c_token++;
  237.         }
  238.         if (!END_OF_COMMAND && almost_equals(c_token, "p$olyline")) {   /* Compare up to $ */
  239.             mif_polyline = TRUE;
  240.             c_token++;
  241.         }
  242.  
  243.         /* Short help */
  244.         if ( !END_OF_COMMAND &&
  245.              (almost_equals(c_token, "h$elp") ||
  246.               almost_equals(c_token, "?$")) ) { /* Compare up to $ */
  247.             fprintf(stderr, "Usage: set terminal mif [options]\n");
  248.             fprintf(stderr, "\toptions:\n");
  249.             fprintf(stderr, "\t\tcolour /        Draw primitives with line types >= 0 in colour (sep. 2-7)\n");
  250.             fprintf(stderr, "\t\tmonochrome      Draw primitives in black (sep. 0)                        \n");
  251.             fprintf(stderr, "\n");
  252.             fprintf(stderr, "\t\tpolyline /      Draw lines as continous curves                           \n");
  253.             fprintf(stderr, "\t\tvectors         Draw lines as collections of vectors                     \n");
  254.             fprintf(stderr, "\n");
  255.             fprintf(stderr, "\t\thelp / ?        Print short usage description on stderr                  \n");
  256.  
  257.             c_token++;
  258.         }
  259.     }
  260.  
  261.     sprintf(term_options, "%s %s", (mif_colour == TRUE)? "colour": "monochrome",
  262.                        (mif_polyline == TRUE)? "polyline": "vectors");
  263. }
  264.  
  265. /* Deallocate the used line structure elements */
  266. static void free_mif_line()
  267. {
  268.     struct mif_line *tline;
  269.  
  270.     while (mif_line.prev != &mif_line) {
  271.         /* Unlink */
  272.         tline = mif_line.prev;
  273.         mif_line.prev = mif_line.prev->prev;
  274.         mif_line.prev->next = &mif_line;
  275.  
  276.         /* Deallocate */
  277.         free(tline);
  278.     }
  279.  
  280.     /* Make sure that the list will be empty */
  281.     mif_line.prev = &mif_line;
  282.     mif_line.next = &mif_line;
  283. }
  284.  
  285. /* Draw the pending line. Change current position. */
  286. static void put_mif_line()
  287. {
  288.     int np, i;
  289.     struct mif_line *tline;
  290.  
  291.     /* Process if inside a Frame */
  292.     if (mif_initialized != 0 && mif_in_frame != 0) {
  293.  
  294.         /* Count the number of available points */
  295.         for (tline = mif_line.next, np = 1; tline != &mif_line; tline = tline->next, np++)
  296.             ;
  297.  
  298.         /* Draw line (at least two points) */
  299.         if (np >= 2) {
  300.  
  301.             /* Line preamble */
  302.             fprintf(outfile, "\t<PolyLine <GroupID %d> %s %s %s\n",
  303.                 MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
  304.  
  305.             /* Draw the line elements */
  306.             fprintf(outfile, "\t\t<NumPoints %d> ", np);
  307.             for (i = 0, tline = &mif_line; i < np; i++, tline = tline->next) {
  308.                 if (i%4 == 0)
  309.                     fprintf(outfile, "\n\t\t");
  310.                 fprintf(outfile, "<Point  %.3f %.3f> ", tline->fpos_x, tline->fpos_y);
  311.             }
  312.  
  313.             /* Line post amble */
  314.             fprintf(outfile, "\n\t>\n");
  315.  
  316.             /* Register the used group ID */
  317.             proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
  318.  
  319.             /* Avoid to redraw this. The MIF system should remember it. */
  320.             mif_pen[0] = '\0';
  321.             mif_pen_width[0] = '\0';
  322.             mif_separation[0] = '\0';
  323.  
  324.             /* Move current position to end of line */
  325.             mif_line.fpos_x = mif_line.prev->fpos_x;
  326.             mif_line.fpos_y = mif_line.prev->fpos_y;
  327.  
  328.             /* Restore the line */
  329.             free_mif_line();
  330.         }
  331.  
  332.     } /* Line processed */
  333. }
  334.  
  335.  
  336. /* Draw a point */
  337. static void mif_put_point(x, y, np)
  338. unsigned int x, y;
  339. int np;
  340. {
  341.    /* Process if inside a Frame */
  342.    if (mif_initialized != 0 && mif_in_frame != 0) {
  343.       
  344.       /* Draw pending line */
  345.       if (mif_polyline == TRUE)
  346.      put_mif_line();
  347.       
  348.       /* Adjust current position for text-graphics alignment */
  349.       MIF_move(x, y);
  350.  
  351.       /* center text */
  352.       MIF_justify_text( CENTRE );
  353.  
  354.       /* Draw the point */
  355.       fprintf(outfile, "\t<TextLine <GroupID %d>\n",
  356.           MIF_PEN_TO_GROUP(mif_pentype) );
  357.  
  358.       MIF_set_font( mif_point[np].font );
  359.       
  360.       fprintf(outfile, "\t\t<TLOrigin  %.3f %.3f> %s <String `%c'>\n",
  361.           mif_line.fpos_x+mif_point[np].x_offset ,
  362.           mif_line.fpos_y+mif_point[np].y_offset,
  363.           mif_justify,
  364.           mif_point[np].chr);
  365.       fprintf(outfile, "\t>\n");
  366.       
  367.       /* Register the used group ID */
  368.       proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
  369.       
  370.       /* Avoid to redraw this. The MIF system should remember it. */
  371.       mif_justify[0] = '\0';
  372.  
  373.    } /* Point processed */
  374. }
  375.  
  376.  
  377. /*
  378.  *  draw points
  379.  */
  380. void MIF_point(x,y,number)
  381. unsigned int x,y;
  382. int number;
  383. {
  384.    if (number < 0) {            /* dot */
  385.       number = -1;
  386.    } else {                /* point */
  387.       number %= POINT_TYPES;
  388.    }
  389.    mif_put_point( x, y, number );
  390. }
  391.  
  392.  
  393. /* Set up a MIF output file */
  394. void MIF_init()
  395. {
  396.     int i;
  397.  
  398.     extern char version[];        /* Declared in ../version.c */
  399.     extern char patchlevel[];
  400.  
  401.     /* Process if not inside a MIF file and Frame */
  402.     if (mif_initialized == 0 && mif_in_frame == 0) {
  403.         /* Tell this terminal driver that the output is initialized and no current frames are processed */
  404.         mif_initialized = 1;
  405.         mif_in_frame = 0;
  406.  
  407.         /* Reset internal position */
  408.         free_mif_line();
  409.         mif_line.fpos_x = GNP_TO_MIF(0);
  410.         mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
  411.  
  412.         /* Reset drawing properties strings */
  413.         mif_pen[0] = '\0';
  414.         mif_pen_width[0] = '\0';
  415.         mif_separation[0] = '\0';
  416.  
  417.         MIF_justify_text( LEFT );
  418.  
  419.         /* Reset group ID generator */
  420.         for (i = 0; i < MIF_NGROUP_ID; i++) {
  421.             mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
  422.             mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
  423.         }
  424.  
  425.         /* Identify ourselves */
  426.         fprintf(outfile, "<MIFFile 3.00> # Generated by gnuplot version %s patchlevel %s; identifies this as a MIF file\n", version, patchlevel);
  427.         fprintf(outfile, "#\n");
  428.  
  429.         /*bs show borders */
  430.         fprintf( outfile, "# show borders\n" );
  431.         fprintf( outfile, "<Document\n<DBordersOn Yes>\n>\n");
  432.  
  433.         /* Setup a default environment to use */
  434.         fprintf(outfile, "# Set a default pen pattern, pen width, unit and font for subsequent objects\n");
  435.         fprintf(outfile, "<Pen 0>\n");
  436.         fprintf(outfile, "<Fill 15>\n");
  437.         fprintf(outfile, "<PenWidth 0.5 pt>\n");
  438.         fprintf(outfile, "<Separation 0>\n");
  439.         fprintf(outfile, "<Units Ucm>\n");
  440.  
  441.         fprintf(outfile, "<FontCatalog\n" );
  442.         fprintf(outfile, 
  443.             "\t<Font <FTag `%s'><FFamily `Times'><FSize %d><FPlain Yes>>\n",
  444.             zgnuplot, MIF_PSIZE );
  445.         fprintf(outfile, 
  446.             "\t<Font <FTag `%s'><FFamily `ZapfDingbats'><FSize 7.0 pt><FPlain Yes>>\n",
  447.             zgnuplotp );
  448.         fprintf(outfile,
  449.             "\t<Font <FTag `%s'><FFamily `Symbol'><FSize 5.0 pt><FPlain Yes>>\n",
  450.             zgnuplotd );
  451.         fprintf(outfile, ">\n" );
  452.  
  453.         fprintf(outfile, "#\n");
  454.     } /* MIF file created */
  455. }
  456.  
  457. /* Finish of a MIF output file */
  458. void MIF_reset()
  459. {
  460.     /* Process if inside a MIF file and not inside a Frame */
  461.     if (mif_initialized != 0 && mif_in_frame == 0) {
  462.         /* Finish off the MIF file */
  463.         fprintf(outfile, "#\n");
  464.         fprintf(outfile, "# End of MIFFile\n");
  465.  
  466.         /* Tell this terminal driver that the output is finished */
  467.         mif_initialized = 0;
  468.  
  469.         /* bs: reset frame number */
  470.         mif_frameno = -1;
  471.  
  472.     } /* MIF file finished */
  473. }
  474.  
  475. /* Start plotting a Frame (-> graphics mode) */
  476. void MIF_graphics()
  477. {
  478.     int i;
  479.  
  480.     /* Process if not inside a Frame */
  481.     if (mif_initialized != 0 && mif_in_frame == 0) {
  482.         /* Tell that this terminal driver is working with a plot frame */
  483.         mif_in_frame = 1;
  484.  
  485.         /* Update frame number */
  486.         mif_frameno++;
  487.  
  488.         /* Set current position */
  489.         free_mif_line();
  490.         mif_line.fpos_x = GNP_TO_MIF(0);
  491.         mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
  492.  
  493.         /* Set drawing properties */
  494.         mif_pen[0] = '\0';
  495.         mif_pen_width[0] = '\0';
  496.         mif_separation[0] = '\0';
  497.  
  498.         MIF_justify_text( LEFT );
  499.  
  500.         /* Reset group ID generator */
  501.         for (i = 0; i < MIF_NGROUP_ID; i++) {
  502.             mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
  503.             mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
  504.         }
  505.  
  506.         /* Frame preamble */
  507.         fprintf(outfile, "#\n");
  508.         fprintf(outfile, "# Frame number %d with plot of graphics\n", mif_frameno);
  509.         fprintf(outfile, "<Frame\n");
  510.         fprintf(outfile, "\t<Pen 15>\n");
  511.         fprintf(outfile, "\t<Fill 15>\n");
  512.         fprintf(outfile, "\t<PenWidth  0.5 pt>\n");
  513.         fprintf(outfile, "\t<Separation 0>\n");
  514. /*bs        fprintf(outfile, "\t<BRect 0.000 %.3f %.3f %.3f>\n",*/
  515.         fprintf(outfile, "\t<BRect 2.000 %.3f %.3f %.3f>\n",
  516.                  ((float) mif_frameno)*GNP_TO_MIF(MIF_YMAX+100), GNP_TO_MIF(MIF_XMAX), GNP_TO_MIF(MIF_YMAX));
  517.         fprintf(outfile, "\t<NSOffset  0.000>\n");
  518.         fprintf(outfile, "\t<BLOffset  0.000>\n");
  519.     } /* Frame created */
  520. }
  521.  
  522. /* Stop plotting a Frame (-> text mode) */
  523. void MIF_text()
  524. {
  525.     int i;
  526.  
  527.     /* Process if inside a Frame */
  528.     if (mif_initialized != 0 && mif_in_frame != 0) {
  529.  
  530.         /* Draw pending line */
  531.         if (mif_polyline == TRUE)
  532.             put_mif_line();
  533.  
  534.         /* Group the used plot primitives */
  535.         fprintf(outfile, "\t#\n");
  536.         fprintf(outfile, "\t# Group the the objects in groups to make the chart easier to manipulate\n");
  537.         fprintf(outfile, "\t# after it's imported into FrameMaker.\n");
  538.  
  539.         for (i = 0; i < MIF_NGROUP_ID; i++) {
  540.             if (mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
  541.                 mif_group_id[i].group_existance == MIF_GROUP_EXISTS) {
  542.                 fprintf(outfile, "\t<Group\n");
  543.                 fprintf(outfile, "\t\t<ID %d>\n", mif_group_id[i].group_id);
  544.                 fprintf(outfile, "\t>\n");
  545.             }
  546.         }
  547.  
  548.         /* Frame post amble */
  549.         fprintf(outfile, ">\n");
  550.         fprintf(outfile, "# End of Frame number %d\n", mif_frameno);
  551.         fprintf(outfile, "#\n");
  552.  
  553.         /* Tell that this terminal driver is not working with a plot frame */
  554.         mif_in_frame = 0;
  555.     } /* Frame finshed */
  556. }
  557.  
  558. /* Select type of line in grapics */
  559. /* NOTE: actually written to output the first time a primitive is drawn AFTER this call */
  560. void MIF_linetype(linetype)
  561. int linetype;           /* -2=border, -1=X/Y-axis, 0-13=lines, and 14-=mapped back */
  562. {
  563.     /* Process if inside a Frame */
  564.     if (mif_initialized != 0 && mif_in_frame != 0) {
  565.  
  566.         /* Draw pending line */
  567.         if (mif_polyline == TRUE)
  568.             put_mif_line();
  569.  
  570.         /* Translate gnuplot pen types to MIF pen types */
  571.         if (linetype < 0) {     /* Special lines */
  572.             if (linetype == -1) {
  573.                 mif_pentype = 8+MIF_NPENS;      /* -1 */
  574.                 if (mif_colour == TRUE)
  575.                     sprintf(mif_separation, " <Separation 0> ");
  576.             }
  577.             else {
  578.                 mif_pentype = 0+MIF_NPENS;      /* -2 or less */
  579.                 if (mif_colour == TRUE)
  580.                     sprintf(mif_separation, " <Separation 0> ");
  581.             }
  582.             sprintf(mif_pen_width, " <PenWidth 1.0 pt> ");
  583.         }
  584.         else {                  /* Normal lines */
  585.             mif_pentype = (linetype)%MIF_NPENS;     /* 0-(MIF_NPENS-1) */
  586.             sprintf(mif_pen_width, " <PenWidth 0.1 pt> ");
  587.             if (mif_colour == TRUE)
  588.                 sprintf(mif_separation, " <Separation %d> ", 2+(mif_pentype%6));        /* 2-7 */
  589.         }
  590.  
  591.         /* Set pen type */
  592.         sprintf(mif_pen, " <Pen %d> ", mif_pattern_table[mif_pentype%MIF_NPENS]);
  593.  
  594.     } /* Primitive processed */
  595. }
  596.  
  597. /* Draw the text horisontally or vertically (90 degrees counterclockwise) */
  598. int MIF_text_angle(ang)
  599. int ang;
  600. {
  601.     if (ang != 0)
  602.     mif_text_ang = MIF_TEXT_VER;
  603.     else
  604.     mif_text_ang = MIF_TEXT_HOR;
  605.  
  606.     return(TRUE);
  607. }
  608.  
  609. /* Justify following text lines (MIF_put_text()) relative to the insertion point */
  610. int MIF_justify_text(mode)
  611. /* NOTE: actually written to output in text primitives which are drawn AFTER this call */
  612. enum JUSTIFY mode;
  613. {
  614.     int rval = TRUE;
  615.  
  616.     /* Process if inside a Frame */
  617.     if (mif_initialized != 0 && mif_in_frame != 0) {
  618.         switch (mode) {
  619.         case LEFT:
  620.            sprintf(mif_justify, " <TLAlignment Left> " );
  621.            break;
  622.         case CENTRE:
  623.            sprintf(mif_justify, " <TLAlignment Center> " );
  624.            break;
  625.         case RIGHT:
  626.            sprintf(mif_justify, " <TLAlignment Right> " );
  627.            break;
  628.         default:
  629.            rval = FALSE;
  630.            break;
  631.         }
  632.  
  633.     } /* Primitive processed */
  634.     else {
  635.         rval = FALSE;
  636.     }
  637.  
  638.     return(rval);
  639. }
  640.  
  641. /* Draw a vector from current position to (x, y) and change current position. */
  642. /* NOTE: actually written to output the first time another primitive is called AFTER this call */
  643. void MIF_vector(x, y)
  644. unsigned int x, y;
  645. {
  646.     /* Process if inside a Frame */
  647.     if (mif_initialized != 0 && mif_in_frame != 0) {
  648.  
  649.         /* Setup the vector as a part of the line */
  650.         insert_mif_line(GNP_TO_MIF(x), GNP_TO_MIF(MIF_YLAST-(int)y));
  651.  
  652.         /* Draw pending line -> vector */
  653.         if (mif_polyline == FALSE)
  654.             put_mif_line();
  655.  
  656.     } /* Vector processed */
  657. }
  658.  
  659. /* Move current position */
  660. void MIF_move(x, y)
  661. unsigned int x, y;
  662. {
  663.     /* Process if inside a Frame */
  664.     if (mif_initialized != 0 && mif_in_frame != 0) {
  665.  
  666.         /* Draw pending line */
  667.         if (mif_polyline == TRUE)
  668.             put_mif_line();
  669.  
  670.         mif_line.fpos_x = GNP_TO_MIF(x);
  671.         mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST-(int)y);
  672.     }
  673. }
  674.  
  675.  
  676. /* set font */
  677. static void MIF_set_font( font )
  678. char *font;
  679. {
  680.    if( font != mif_font ) {
  681.       fprintf(outfile, "\t\t<Font\n\t\t\t<FTag `%s'>\n\t\t>\n", font );
  682.       mif_font = font;
  683.    }
  684. }
  685.  
  686.  
  687. /* Draw the text string str at (x, y). Adjust according to MIF_justify_text(). Change current position. */
  688. void MIF_put_text(x, y, str)
  689. unsigned int x, y;
  690. char str[];
  691. {
  692.     /* Process if inside a Frame */
  693.     if (mif_initialized != 0 && mif_in_frame != 0) {
  694.  
  695.         /* Draw pending line */
  696.         if (mif_polyline == TRUE)
  697.             put_mif_line();
  698.  
  699.         /* Adjust current position for text-graphics alignment */
  700.         MIF_move(x, y-MIF_VCHAR/5);
  701.  
  702.         if (strlen(str) > 0) {
  703.  
  704.             /* Draw the text */
  705.             fprintf(outfile, "\t<TextLine <GroupID %d> %s %s %s\n",
  706.                 MIF_PEN_TO_GROUP(mif_pentype), mif_pen,
  707.                 mif_pen_width, mif_separation);
  708.  
  709.             MIF_set_font( zgnuplot );
  710.  
  711.             fprintf(outfile, "\t\t<TLOrigin  %.3f %.3f> %s %s <String `%s'>\n",
  712.                      mif_line.fpos_x, mif_line.fpos_y, mif_justify,
  713.                      (mif_text_ang == MIF_TEXT_VER)? "<Angle 90>": "",
  714.                      str);
  715.             fprintf(outfile, "\t>\n");
  716.  
  717.             /* Register the used group ID */
  718.             proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
  719.  
  720.             /* Avoid to redraw this. The MIF system should remember it. */
  721.             mif_pen[0] = '\0';
  722.             mif_pen_width[0] = '\0';
  723.             mif_separation[0] = '\0';
  724.  
  725.             mif_justify[0] = '\0';  /* Independent of linetype */
  726.         }
  727.     } /* Text processed */
  728. }
  729.  
  730.  
  731. /* Insert one point in the line */
  732. static int insert_mif_line(fx, fy)
  733. double fx, fy;
  734. {
  735.     int rval = TRUE;
  736.  
  737.     if ((mif_line.prev->next = (struct mif_line *) alloc(sizeof(struct mif_line),"MIF driver")) != (struct mif_line *) NULL) {
  738.         /* Link */
  739.         mif_line.prev->next->next = &mif_line;
  740.         mif_line.prev->next->prev = mif_line.prev;
  741.         mif_line.prev = mif_line.prev->next;
  742.  
  743.         /* Fill */
  744.         mif_line.prev->fpos_x = fx;
  745.         mif_line.prev->fpos_y = fy;
  746.  
  747.         rval = TRUE;
  748.     }
  749.     else { /* Failed to allocate */
  750.         /* Relink */
  751.         mif_line.prev->next = &mif_line;
  752.  
  753.         rval = FALSE;
  754.     }
  755.  
  756.     return(rval);
  757. }
  758.  
  759. /* Register group ID. Update group ID existance. */
  760. /* Returns:     1       group_id belongs to a MIF group
  761.         0       group_id does not belong to a MIF group
  762.            -1       not inside a Frame
  763.            -2       group ID list is full
  764.  */
  765. static int proc_group_id(group_id)
  766. int group_id;
  767. {
  768.     int i, rval = 0;
  769.  
  770.     /* Process if inside a Frame */
  771.     if (mif_initialized != 0 && mif_in_frame != 0) {
  772.  
  773.         /* Find out the group ID, or a free group ID slot index. */
  774.         for (i = 0; i < MIF_NGROUP_ID &&
  775.                 mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
  776.                 mif_group_id[i].group_id != group_id;
  777.                                         i++) {
  778.             /* Don't check the group_existance variable */
  779.         }
  780.  
  781.         if (i < MIF_NGROUP_ID) {
  782.             if (mif_group_id[i].group_id == MIF_INVALID_GROUP_ID) {
  783.                 /* Register as new group ID for eventual use as MIF group */
  784.                 mif_group_id[i].group_id = group_id;
  785.                 mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
  786.             }
  787.             else {
  788.                 /* If second use of this group ID -> create a new MIF group */
  789.                 if (mif_group_id[i].group_id == group_id) {
  790.                     mif_group_id[i].group_existance = MIF_GROUP_EXISTS;
  791.                     /* NOTE: a group MUST have at least two members. */
  792.                     rval = 1;
  793.                 }
  794.             }
  795.         }
  796.         else {
  797.             rval = -2;      /* No place for this group ID in the list */
  798.         }
  799.  
  800.     } /* Group ID processed */
  801.     else {
  802.         rval = -1;      /* Not inside a Frame */
  803.     }
  804.  
  805.     /* Return MIF group status */
  806.     return(rval);
  807. }
  808.  
  809.  
  810. #endif
  811.  
  812.  
  813. #ifdef TERM_TABLE
  814.  
  815. TERM_TABLE_START(mif_driver)
  816.  
  817.     "mif", "Frame maker MIF 3.00 format",
  818.     MIF_XMAX, MIF_YMAX, MIF_VCHAR, MIF_HCHAR, 
  819.     MIF_VTIC, MIF_HTIC, MIF_options, MIF_init, MIF_reset, 
  820.     MIF_text, null_scale, MIF_graphics, MIF_move, MIF_vector, 
  821.     MIF_linetype, MIF_put_text, MIF_text_angle, 
  822.     MIF_justify_text, MIF_point, do_arrow, set_font_null}
  823.  
  824. #undef LAST_TERM
  825. #define LAST_TERM mif_driver
  826. #endif
  827. #endif /* TERM_PROTO_ONLY */
  828.  
  829.  
  830. #ifdef TERM_HELP
  831. START_HELP(mif)
  832. "1 mif",
  833. "?set terminal mif",
  834. "?mif",
  835. " Several options may be set in the MIF 3.00 driver.",
  836. "",
  837. " Syntax:",
  838. "      set terminal mif {<pentype>} {<curvetype>} {<help>}",
  839. "",
  840. " <pentype> selects \"colour\" of the graphics.",
  841. "      `colour`     plot lines with line types >= 0 in colour (MIF sep. 2--7).",
  842. "      `monochrome` plot all line types in black (MIF sep. 0).",
  843. "",
  844. " <curvetype> selects how \"curves\" are plotted.",
  845. "      `polyline`   plot curves as continuous curves.",
  846. "      `vectors`    plot curves as collections of vectors",
  847. "",
  848. " <help> print online help on standard error output.",
  849. "      `help`       print a short description of the usage, and the options",
  850. "      `?`          print a short description of the usage",
  851. "",
  852. " This terminal driver produces Frame Maker MIF format version 3.00.  It plots",
  853. " in MIF Frames with the size 15*10 [cm], and plot primitives with the same pen",
  854. " will be grouped in the same MIF group.  Plot primitives in a `gnuplot` plot",
  855. " will be plotted in a MIF Frame, and several MIF Frames are collected in one",
  856. " large MIF Frame.  Plot primitives with line types >= 0 will as default be",
  857. " drawn in color.  As default, curves are plotted as continuous lines.  The MIF",
  858. " font used for text is \"Times\".",
  859. "",
  860. " Examples:",
  861. "      set term mif",
  862. "      set term mif vectors",
  863. "      set term mif help"
  864. END_HELP(mif)
  865. #endif
  866.  
  867.